/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * Licensed under Simplified BSD License
 *
 *
 * @author: jin Chen 
 * @date: Nov 18, 2007$
 * @version: 1.0
 */
package edu.psu.geovista.app.gmatrix.canvas;

import java.awt.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class MatrixCanvasContext {
    public static final int  LAYOUT_TOP_BOTTOM=1;
    public static final int  LAYOUT_BOTTOM_TOP=2;
    public static final int RATIO_FULLSIZE=1;
     //GUI
    private int layouttype=LAYOUT_BOTTOM_TOP;//LAYOUT_TOP_BOTTOM;//LAYOUT_BOTTOM_TOP;
    protected int numOfRow;
    protected int numOfCulumn;
    protected GridLine gridline;
    Dimension cellSize;
    ComponentOrientation componentOrientation;

    boolean style3d=false; //if true, all cells painted in 3D style

     Set<Point> selectedCell=new HashSet<Point>(0); // 
     Point highlightedCell;


    Color defaultForeground=Color.gray;
    Color defaultBackground=Color.black;

    Color[][] foreground;
    Color[][] background;

    Symbol defaultSymbol=new RectangleSymbol();
    Symbol[][] symbols;

    public MatrixCanvasContext() {
        this.gridline =new GridLine();
    }


    /*******************************************************************************************************
     *                states
     *******************************************************************************************************/
    /**
     *
     * @param row
     * @param col
     * @return    a symbol for a row/col index
     */
    public Symbol getSymbol(int row,int col) {
        if(symbols==null) return this.getDefaultSymbol() ;
        Symbol symbol = symbols[row][col];
        if(symbol==null) return this.getDefaultSymbol() ;
        return symbol;
    }

    public void setSymbols(Symbol[][] symbols) {
        this.symbols = symbols;
    }

    public Symbol getDefaultSymbol() {
        return defaultSymbol;
    }

    public void setDefaultSymbol(Symbol defaultSymbol) {
        this.defaultSymbol = defaultSymbol;
    }
    public Color getBackground(int row, int col) {
        if(background==null) return defaultBackground;
        else
            return background[row][col];
    }

    public void setBackground(Color[][] background) {
        this.background = background;
    }

    public Color getForeground(int row, int col) {
        if(foreground==null) return defaultForeground;
        else
            return foreground[row][col];
    }

    public Color[][] getForeground() {
        return foreground;
    }

    public void setForeground(Color[][] foreground) {
        this.foreground = foreground;
    }

    public boolean isStyle3d() {
        return style3d;
    }

    public void setStyle3d(boolean style3d) {
        this.style3d = style3d;
    }


    public Dimension getCellSize() {
        return cellSize;
    }

    public void setCellSize(Dimension cellSize) {
        this.cellSize = cellSize;
    }
     public void setComponentOrientation(ComponentOrientation o) {
         componentOrientation=o;

    }


    public ComponentOrientation getComponentOrientation() {
        return componentOrientation;
    }

    public GridLine getGridline() {
        return gridline;
    }

    public void setGridline(GridLine gridline) {
        this.gridline = gridline;
    }

    public int getLayouttype() {
        return layouttype;
    }

    public void setLayouttype(int layouttype) {
        this.layouttype = layouttype;
    }

    public int getNumOfCulumn() {
        return numOfCulumn;
    }

    public void setNumOfCulumn(int numOfCulumn) {
        this.numOfCulumn = numOfCulumn;
    }

    public int getNumOfRow() {
        return numOfRow;
    }

    public void setNumOfRow(int numOfRow) {
        this.numOfRow = numOfRow;
    }

    /*******************************************************************************************************
     *                runtime calculated attributes
     *******************************************************************************************************/

     public Dimension computeCellSize(Dimension size){

        Dimension gap = gridline.getSize();
        int h = (size.height-gap.height*(numOfRow-1))/numOfRow;
        int w = (size.width-gap.width *(numOfCulumn-1)) /numOfCulumn;
        return new Dimension(w,h);

    }
    /**
     *  remove  Dimension swatchSize

     * @param arow     index of swatch, map to colors' index
     * @param acol
     * @return  r
     */
    public  Rectangle computeCellBound(int arow, int acol){
        Dimension cellSize=this.getCellSize() ;
        int row=0, column=acol;
        Dimension gap = gridline.getSize();
        if(this.layouttype==LAYOUT_BOTTOM_TOP){
            row=numOfRow-arow -1;//1st swatch in bottom row( 1st row is on top)

        }
        else {
            row=arow;
        }

                int x;
                if ((!this.getComponentOrientation().isLeftToRight()) ) {
                    x = (numOfCulumn - column - 1) * (cellSize.width + gap.width);
                } else {
                    x = column * (cellSize.width + gap.width);
                }
                int y = row * (cellSize.height + gap.height);
                return new Rectangle(x,y,cellSize.width ,cellSize.height );
    }


    public float getSymbolSizeRatio(int row, int col){
          float fullsize=RATIO_FULLSIZE;
        float halfsize=RATIO_FULLSIZE/2.0f;
        float sizeratio=fullsize;
        //2. found if there is selection
        boolean hasSelection=false;//true if there is some swatch in selected mode
        if(this.selectedCell.size() >0){
            hasSelection=true;
        }
        if(hasSelection){
            if(isSelected(row,col) ){
                sizeratio=fullsize;


            }
            else{
                sizeratio=halfsize;//paintComponent(g2d,Swatch.PAINT_MODE_REDUCED);

            }
        }
        else {
            sizeratio=fullsize;


        }
        return sizeratio;
    }

    public Rectangle computeSymbolBoundary(int row, int col) {
        float symbolSizeRatio = this.getSymbolSizeRatio(row, col);
        Rectangle cellbound = this.computeCellBound(row, col);
        int w = (int) (cellbound.width * symbolSizeRatio);
        int h = (int) (cellbound.height * symbolSizeRatio);
        return new Rectangle(cellbound.x, cellbound.y,w,h);
    }



    public boolean isSelected(int row, int col) {
        Point cellindex=new Point(row,col);
        Set<Point> selectedCell = this.selectedCell;
        for (Iterator iterator = selectedCell.iterator(); iterator.hasNext();) {
            Point aindex = (Point) iterator.next();
            if(aindex.equals(cellindex) ){
                return true;
            }

        }
        return false;

    }


    public static interface SelectionSupport{
        /**
         *
         * @return true if any cell is selected; false if no cell or all cell are selected
         */
        public boolean hasSelection();

        /**
         *
         * @param row
         * @param col
         * @return    true if  cell at (row,col) is selected
         */
        public boolean isSelected(int row, int col);
    }


}
